// 命令接口，定义了命令执行的抽象方法
interface Command {
    void execute();
}

// 具体的命令类：打开灯光命令
class LightOnCommand implements Command {
    private Light light;

    // 通过构造函数传入灯光对象，使得命令与具体的接收者（灯光）关联起来
    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.turnOn();
    }
}

// 具体的命令类：关闭灯光命令
class LightOffCommand implements Command {
    private Light light;

    public LightOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.turnOff();
    }
}

// 接收者类：灯光，代表具体执行命令的对象
class Light {
    // 私有方法，用于实际打开灯光的操作，外部无法直接调用，增强封装性
    private void turnOnInner() {
        System.out.println("The light is on.");
    }

    // 私有方法，用于实际关闭灯光的操作，外部无法直接调用，增强封装性
    private void turnOffInner() {
        System.out.println("The light is off.");
    }

    // 公共方法，对外提供打开灯光的接口
    public void turnOn() {
        turnOnInner();
    }

    // 公共方法，对外提供关闭灯光的接口
    public void turnOff() {
        turnOffInner();
    }
}

// 调用者类：开关，用于设置和执行命令
class SwitchControl {
    private Command command;

    // 设置要执行的命令
    public void setCommand(Command command) {
        this.command = command;
    }

    // 执行当前设置的命令
    public void executeCommand() {
        if (command!= null) {
            command.execute();
        } else {
            System.out.println("No command has been set.");
        }
    }
}

// 测试命令模式的主类，包含main方法
public class CommandPatternDemo {
    public static void main(String[] args) {
        // 创建灯光对象，作为命令的接收者
        Light light = new Light();

        // 创建打开灯光的命令对象，并关联对应的灯光
        Command lightOnCommand = new LightOnCommand(light);

        // 创建关闭灯光的命令对象，并关联对应的灯光
        Command lightOffCommand = new LightOffCommand(light);

        // 创建开关对象
        SwitchControl switchControl = new SwitchControl();

        // 设置并执行打开灯光的命令
        switchControl.setCommand(lightOnCommand);
        switchControl.executeCommand();

        // 设置并执行关闭灯光的命令
        switchControl.setCommand(lightOffCommand);
        switchControl.executeCommand();

        // 测试未设置命令时执行的情况
        SwitchControl switchWithoutCommand = new SwitchControl();
        switchWithoutCommand.executeCommand();
    }
}